Implement localized slug-based routing using either Next.js built-in i18n routing with a catch-all dynamic route and a slug mapping system, or use a dedicated library like next-roots that generates language-specific route folders at build time
Implementing localized slug-based routing in Next.js requires handling both the language prefix and the translated path segments. For URLs like /en/products/shoes and /fr/produits/chaussures, you need a system that maps the same underlying content to different URL structures based on language. Next.js offers several approaches: using built-in i18n routing with a dynamic [locale] folder and a slug translation layer, or using specialized libraries like next-roots that pre-generate all language-specific routes at build time. The choice depends on whether you need static generation for all language variants or prefer a more dynamic approach [citation:5][citation:2][citation:6].
Next.js has built-in internationalized routing since version 10.0.0, which handles locale prefixes automatically [citation:5]. For slug translation, you can combine this with a dynamic route structure. In your next.config.js, configure your supported locales. Then create a dynamic route folder [locale] that contains your pages. For the slug translation itself, you need to implement a mapping system—either in your data fetching logic or via a middleware—that converts the localized slug to a canonical identifier and fetches the correct content [citation:1][citation:5]. The Optimizely documentation shows this pattern with a [locale]/[slug] structure where the page component fetches content based on both parameters [citation:1].
The next-intl library provides a more complete solution for internationalization, including routing, translations, and locale management. It integrates seamlessly with Next.js App Router and handles the complexity of localized routes, including slug translation. You define your routing configuration, and next-intl provides middleware for locale negotiation and components for navigation that automatically handle translated paths [citation:2]. This approach gives you both the locale prefix routing and the ability to manage translated content through your data layer.
For projects that need fully static, pre-generated routes with translated slugs, next-roots offers an alternative approach. Instead of using dynamic [locale] segments, it generates actual folders for each language at build time. You maintain your original routes in a roots folder, and next-roots creates language-specific routes (e.g., (en)/products/shoes and fr/produits/chaussures) by reading translation files. This approach gives you the full benefits of static generation and type-safe links, but requires running a generation step whenever routes or translations change [citation:3][citation:6].
Regardless of which routing approach you choose, you need a strategy for slug translation in your data layer. The Contentful documentation demonstrates fetching content based on both locale and slug parameters, where each content entry stores its slug for each supported language [citation:7]. In your API or database, you should store a mapping of (locale, slug) → contentId or include all language slugs on each content item. This allows your getProductBySlug(slug, locale) function to retrieve the correct content regardless of which language's slug is used in the URL [citation:7].
SEO implications: Using different URLs for different languages is good for SEO, but ensure you implement proper hreflang tags to indicate language alternatives to search engines [citation:5].
Static generation: For dynamic routes with getStaticProps, you must return all locale variants from getStaticPaths to pre-render every language version [citation:5].
Default locale prefix: By default, Next.js does not prefix the default locale (e.g., /en for English). If you want all languages to have prefixes, you can configure this via middleware or use libraries like next-intl that support this [citation:2][citation:5].
Dynamic parameters: When using libraries like next-roots, you get type-safe links and automatic locale detection in your navigation components, reducing the risk of broken links [citation:3][citation:6].